package vashion.azeroth.core.yvogue.sftp;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Vector;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.SimpleHttpConnectionManager;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Maps;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

import vashion.azeroth.core.yvogue.pojo.YvogueBrand;
import vashion.azeroth.core.yvogue.pojo.YvogueBrandList;
import vashion.azeroth.core.yvogue.pojo.YvogueProduct;
import vashion.azeroth.core.yvogue.pojo.YvogueProductList;
import vashion.azeroth.core.yvogue.xml.XMLUtil;

/**
 * sftp工具。注意：构造方法有两个：分别是基于密码认证、基于秘钥认证。
 * 
 * @see http://xliangwu.iteye.com/blog/1499764
 * @author Somnus
 */
public class SFTPUtil {
	private transient Logger log = LoggerFactory.getLogger(this.getClass());

	private ChannelSftp sftp;

	private Session session;
	/** FTP 登录用户名 */
	private String username;
	/** FTP 登录密码 */
	private String password;
	/** 私钥文件的路径 */
	private String keyFilePath;
	/** FTP 服务器地址IP地址 */
	private String host;
	/** FTP 端口 */
	private int port;

	/**
	 * 构造基于密码认证的sftp对象
	 * 
	 * @param userName
	 * @param password
	 * @param host
	 * @param port
	 */
	public SFTPUtil(String username, String password, String host, int port) {
		this.username = username;
		this.password = password;
		this.host = host;
		this.port = port;
	}

	/**
	 * 构造基于秘钥认证的sftp对象
	 * 
	 * @param userName
	 * @param host
	 * @param port
	 * @param keyFilePath
	 */
	public SFTPUtil(String username, String host, int port, String keyFilePath) {
		this.username = username;
		this.host = host;
		this.port = port;
		this.keyFilePath = keyFilePath;
	}

	public SFTPUtil() {
	}

	/**
	 * 连接sftp服务器
	 * 
	 * @throws Exception
	 */
	public void login() throws Exception {
		try {
			JSch jsch = new JSch();
			if (keyFilePath != null) {
				jsch.addIdentity(keyFilePath);// 设置私钥
				log.info("sftp connect,path of private key file：{}", keyFilePath);
			}
			log.info("sftp connect by host:{} username:{}", host, username);

			session = jsch.getSession(username, host, port);
			log.info("Session is build");
			if (password != null) {
				session.setPassword(password);
			}
			Properties config = new Properties();
			config.put("StrictHostKeyChecking", "no");

			session.setConfig(config);
			session.connect();
			log.info("Session is connected");

			Channel channel = session.openChannel("sftp");
			channel.connect();
			log.info("channel is connected");

			sftp = (ChannelSftp) channel;
			log.info(String.format("sftp server host:[%s] port:[%s] is connect successfull", host, port));
		} catch (JSchException e) {
			log.error("Cannot connect to specified sftp server : {}:{} \n Exception message is: {}",
					new Object[] { host, port, e.getMessage() });
			throw new Exception(e.getMessage(), e);
		}
	}

	/**
	 * 关闭连接 server
	 */
	public void logout() {
		if (sftp != null) {
			if (sftp.isConnected()) {
				sftp.disconnect();
				log.info("sftp is closed already");
			}
		}
		if (session != null) {
			if (session.isConnected()) {
				session.disconnect();
				log.info("sshSession is closed already");
			}
		}
	}

	/**
	 * 下载文件
	 * 
	 * @param directory
	 *            下载目录
	 * @param downloadFile
	 *            下载的文件
	 * @param saveFile
	 *            存在本地的路径
	 * @throws SftpException
	 * @throws FileNotFoundException
	 * @throws Exception
	 */
	public void download(String directory, String downloadFile, String saveFile)
			throws SftpException, FileNotFoundException {
		if (directory != null && !"".equals(directory)) {
			sftp.cd(directory);
		}
		File file = new File(saveFile);
		sftp.get(downloadFile, new FileOutputStream(file));
		log.info("file:{} is download successful", downloadFile);
	}

	/**
	 * 下载文件
	 * 
	 * @param directory
	 *            下载目录
	 * @param downloadFile
	 *            下载的文件名
	 * @return 字节数组
	 * @throws SftpException
	 * @throws IOException
	 * @throws Exception
	 */
	public String download(String directory, String downloadFile) throws SftpException, IOException {
		if (directory != null && !"".equals(directory)) {
			sftp.cd(directory);
		}
		InputStream is = sftp.get(downloadFile);

		String fileData = IOUtils.toString(is, "UTF-8");

		log.info("file:{} is download successful", downloadFile);
		return fileData;
	}

	/**
	 * 列出目录下的文件
	 * 
	 * @param directory
	 *            要列出的目录
	 * @param sftp
	 * @return
	 * @throws SftpException
	 */
	public Vector<?> listFiles(String directory) throws SftpException {
		return sftp.ls(directory);
	}
	
	public static String getProcuctPics(String url) throws Exception {
		HttpClient client = new HttpClient(new HttpClientParams(), new SimpleHttpConnectionManager(true));
		GetMethod method = new GetMethod(url);   
	    //设置头信息：如果不设置User-Agent可能会报405，导致取不到数据  
		method.setRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:39.0) Gecko/20100101 Firefox/39.0");  
	    //使用系统提供的默认的恢复策略    
		method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler()); 
		try {
			int result = client.executeMethod(method);
			if (result == HttpStatus.SC_OK) {
				InputStream in = method.getResponseBodyAsStream();
				ByteArrayOutputStream baos = new ByteArrayOutputStream();
				byte[] buffer = new byte[1024];
				int len = 0;
				while ((len = in.read(buffer)) != -1) {
					baos.write(buffer, 0, len);
				}
				return URLDecoder.decode(baos.toString(), "UTF-8");
			} else {
				throw new Exception("HTTP ERROR Status: " + method.getStatusCode() + ":" + method.getStatusText());
			}
		} finally {
			method.releaseConnection();
			}
		}

	public static void main(String[] args) throws Exception {
		Map<String, YvogueBrand> yvogueBrandMap = getYvogueBrandList();
		SFTPUtil sftp = new SFTPUtil("inventory", "Ihxy&L", "121.40.188.248", 22);
		sftp.login();
		String xmlStr = sftp.download("./", "inventory.inc.xml");
//		System.out.println(xmlStr);
		sftp.logout();
		YvogueProductList yvogueProductList = (YvogueProductList) XMLUtil.convertXmlStrToObject(YvogueProductList.class,
				xmlStr.replaceAll("<inventory>", "").replaceAll("</inventory>", ""));
		Iterator<YvogueProduct> it = yvogueProductList.iterator();
		String cataList = new String();
		while (it.hasNext()) {
			YvogueProduct item = (YvogueProduct) it.next();
			StringBuffer mainImgGetURL = new StringBuffer("http://img.yvogue.hk/pimg/pl/")
					.append(yvogueBrandMap.get(item.getBrand()).getId())
					.append("/m").append(item.getModel().toLowerCase())
					.append("/m").append(item.getMaterial().toLowerCase())
					.append("/c").append(item.getColor().toLowerCase()).append(".jpg");
			StringBuffer imgGetURL = new StringBuffer("http://img.yvogue.hk/pimg/ll/")
					.append(yvogueBrandMap.get(item.getBrand()).getId())
					.append("/m").append(item.getModel().toLowerCase())
					.append("/m").append(item.getMaterial().toLowerCase())
					.append("/c").append(item.getColor().toLowerCase());
			String picUrl = getProcuctPics(imgGetURL.toString());
			picUrl = picUrl.substring(picUrl.lastIndexOf('[') + 1, picUrl.lastIndexOf(']')).replaceAll("\"", "");
			String[] picUrlList = picUrl.split(",");
			StringBuffer desPicUrlBuffer = new StringBuffer();
			for (String picUrlTemp : picUrlList) {
				desPicUrlBuffer.append("http://img.yvogue.hk").append(picUrlTemp.trim()).append(",");
			}
			String desPicUrl = desPicUrlBuffer.toString();
			System.out.println(desPicUrl);
			System.out.println("First Pic: " + mainImgGetURL.toString());
			String cata = item.getCate();
			if (!cataList.contains(cata)) {
				cataList = cataList + " " + cata;
				System.out.println(item.getCate());
			}
		}
	}
	
	private static Map<String, YvogueBrand> getYvogueBrandList() {
		Map<String, YvogueBrand> yvogueBrandMap = Maps.<String, YvogueBrand>newHashMap();
		SFTPUtil sftp = new SFTPUtil("inventory", "Ihxy&L", "121.40.188.248", 22);
		try {
			sftp.login();

			String xmlStr = sftp.download("./", "brands.xml");
			sftp.logout();
			YvogueBrandList yvogueBrandList = (YvogueBrandList) XMLUtil.convertXmlStrToObject(YvogueBrandList.class,
					xmlStr);
			Iterator<YvogueBrand> it = yvogueBrandList.iterator();
			while (it.hasNext()) {
				YvogueBrand yvogueBrandTemp = (YvogueBrand) it.next();
				yvogueBrandMap.put(yvogueBrandTemp.getName(), yvogueBrandTemp);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return yvogueBrandMap;
	}
}
